package com.mk.common.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class BigDecimalDemo
{

	/**
	 * 保留两位小数
	 */
	@Test
	public void test1() {
		BigDecimal fund = new BigDecimal("");
		BigDecimal avgFund = fund.divide(new BigDecimal(2), 2, BigDecimal.ROUND_HALF_UP);
//		BigDecimal avgFund = fund.divide(new BigDecimal(2),  BigDecimal.ROUND_HALF_UP);
		System.out.println(avgFund.doubleValue()); //1195.06

	}
	
	/**
	 * 两数相加
	 */
	@Test
	public void test2() {
		BigDecimal incomeFamilyTotal = new BigDecimal("0");
		BigDecimal incomeAfterRemit = new BigDecimal("120");
		incomeFamilyTotal.add(incomeAfterRemit);
		
		System.out.println(incomeFamilyTotal.toString()); // 0
		System.out.println(incomeFamilyTotal); // 0
		
		incomeFamilyTotal = incomeFamilyTotal.add(incomeAfterRemit);
		System.out.println(incomeFamilyTotal.toString());//120
	}
	
	@Test
	public void test3() {
		BigDecimal money = new BigDecimal("1197.07");
		money = money.setScale(0, BigDecimal.ROUND_UP);
		
		System.out.println(money); //1198
	}
	
	@Test
	public void test4() {
		DecimalFormat df1 = new DecimalFormat("#.00");
		
		String val = "98.00";
		double doubleNum = Double.parseDouble(val);
		String _dou = df1.format(doubleNum);
		
		System.out.println( _dou ); // 98.00
		System.out.println( Double.parseDouble(_dou) );
	}
	
	@Test
	public void test5() {
		BigDecimal df = new BigDecimal("104.0");
		System.out.println(df.intValue()); // 104
		System.out.println(df.intValue()); // 
		
	}
	
	/**
	 * 极其容易忽略的异常
	 */
	@Test
	public void test6() {
		Double num = 0.1;
		BigDecimal bd = new BigDecimal(num);
		BigDecimal bc = new BigDecimal("0.1");
		BigDecimal ce = new BigDecimal(Double.toString(0.1));
		BigDecimal d1 = BigDecimal.valueOf(0.1);
		
//		System.out.println(95.5-100.0); // -4.5
//		System.out.println(0.1 + 0.2);  // 0.30000000000000004
//		System.out.println(bd);  // 0.1000000000000000055511151231257827021181583404541015625
//		System.out.println(bc);  // 0.1
//		System.out.println(ce);  // 0.1
		System.out.println(d1);  // 0.1
	}
	
	@Test 
	public void test7() {
		BigDecimal full = new BigDecimal("100.0");
		BigDecimal score = new BigDecimal("95.5");
		
		System.out.println(full.subtract(score));
	}
	
	
	/**
	 * 加法的坑
	 */
	@Test
	public void test8() {
		BigDecimal full = new BigDecimal("100.0");
		BigDecimal score = new BigDecimal("95.5");
		
		System.out.println(full.add(score)); // 195.5
		System.out.println(full.toString()); // 100.0
		System.out.println(full); // 100.0
	}
	
	@Test
	public void test9() {
		BigDecimal full = new BigDecimal("100.0").add(new BigDecimal("98.5"));
		System.out.println(full);   // 198.5
		System.out.println(full.toString()); // 198.5
	}
	
	/**
	 * 减法
	 */
	@Test
	public void test10() {
		System.out.println( new BigDecimal("1.1").subtract(new BigDecimal("0.1")) ); // 1.0
		System.out.println( String.valueOf(new BigDecimal("1.1").subtract(new BigDecimal("0.1"))) ); // 1.0
	}
	
	/**
	 * 小数点问题。 如果等于整数，去掉小数点，否则保留
	 */
	@Test
	public void test11() {
		BigDecimal dc = new BigDecimal("100.0");
		
		System.out.println(dc); //100.0
		System.out.println(dc.toString()); // 100.0
		System.out.println(String.valueOf(dc)); //100.0
		
		System.out.println(dc.intValue()); // 100
		System.out.println(String.valueOf(dc.intValue())); // 100
	}
	
	@Test
	public void test12() {
		Double num = (double) 0;
		BigDecimal calc = new BigDecimal(num);
		
		System.out.println(calc);
	}
	
	
	@Test
	public void test13() {
		BigDecimal fullMarks = new BigDecimal("100.0");
		
		System.out.println(fullMarks.doubleValue()==fullMarks.intValue()); // true
		System.out.println( fullMarks.doubleValue()==fullMarks.intValue() ? fullMarks.intValue():fullMarks.doubleValue());// 100.0
		System.out.println( String.valueOf(fullMarks.doubleValue()==fullMarks.intValue() ? fullMarks.intValue():fullMarks.doubleValue()) ); //100.0  
		System.out.println( fullMarks.doubleValue()==fullMarks.intValue() 
				? String.valueOf(fullMarks.intValue()):String.valueOf(fullMarks)); // 100
	}
	
	
	@Test
	public void test14() {
		BigDecimal d = new BigDecimal("97.0");
		BigDecimal res = d.divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_UP);
		
		System.out.println(res);
	}
	
	@Test
	public void test15() {
		List<Double> list = Arrays.asList(0.1, 0.2);
//		System.out.println(0.1+0.2); // 0.30000000000000004
		
//		Double sum = list.stream().collect(Collectors.summingDouble(item->item));
//		System.out.println(sum); // 0.30000000000000004
		
		
//		Double sum = list.stream().mapToDouble(Double::doubleValue).sum();
//		System.out.println(sum); // 0.30000000000000004
		
//		BigDecimal sum = list.stream()
//				.map(BigDecimal::new).reduce(new BigDecimal("0.0"), BigDecimal::add);
//		System.out.println(sum.doubleValue()); // 0.30000000000000004
		
//		DoubleSummaryStatistics stats = list.stream().mapToDouble(Double::doubleValue).summaryStatistics();
//		System.out.println(stats.getSum()); // 0.30000000000000004

//		BigDecimal sum = list.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add);
//		System.out.println(sum);  // 0.3 
		
		BigDecimal sum = list.stream().map(t->new BigDecimal(String.valueOf(t))).reduce(BigDecimal.ZERO, BigDecimal::add);
		System.out.println(sum); // 0.3
	}
	
	@Test
	public void test16() {
		BigDecimal fullMarks = new BigDecimal("100.0");
		BigDecimal deduct = new BigDecimal("17.0");
		BigDecimal divisor = new BigDecimal(2L);
		System.out.println(fullMarks.subtract(deduct).divide(divisor,2, BigDecimal.ROUND_HALF_UP).doubleValue());
	}
	
	@Test
	public void testValAndPoint() {
		BigDecimal fullMarks = BigDecimal.valueOf(100.0);
		BigDecimal deduct = fullMarks;
		BigDecimal score = deduct.subtract(new BigDecimal("80.01"));
		
		System.out.println(score.toPlainString());
		System.out.println(deduct.toPlainString());
		System.out.println(fullMarks.toPlainString());
	}
	
}
